import { Message, Modal, Switch, Tabs } from '@arco-design/web-react'
import { IconDelete, IconEdit } from '@arco-design/web-react/icon'
import {
    closestCenter,
    DndContext,
    DragEndEvent,
    KeyboardSensor,
    PointerSensor,
    useSensor,
    useSensors,
} from '@dnd-kit/core'
import {
    horizontalListSortingStrategy,
    SortableContext,
    sortableKeyboardCoordinates,
    useSortable,
} from '@dnd-kit/sortable'
import classNames from 'classnames'
import React from 'react'
import { IGroupItem, IListItem } from '../../../../utils/interfaces'
import { apiStore } from '../../../../utils/store/apiStore'
import ContextMenu from '../../components/ContextMenu'
import AddGroupModal from './AddGroupModal'

const { TabPane } = Tabs

// TabTitle 组件的 Props
interface TabTitleProps {
    hasDragging?: boolean
    item: IGroupItem
    setEditingItem: (item: IListItem | undefined) => void
    handleDelete: (item: IListItem) => void
    handleGroupChange: (item: IListItem, enabled: boolean) => void
}

// TabPane 的 Title 组件（支持拖拽）
const TabTitle: React.FC<TabTitleProps> = ({
    hasDragging,
    item,
    setEditingItem,
    handleDelete,
    handleGroupChange,
}) => {
    const [isHover, setIsHover] = useState(false)

    // useSortable hook 提供拖拽能力
    const {
        attributes,
        listeners,
        setNodeRef,
        transform,
        transition,
        isDragging,
    } = useSortable({ id: item.id })

    // 拖拽开始时清除 hover 状态
    useEffect(() => {
        if (isDragging) {
            setIsHover(false)
        }
    }, [isDragging])

    const style = {
        transform: transform
            ? `translate3d(${transform.x}px, ${transform.y}px, 0)`
            : undefined,
        transition,
        opacity: isDragging ? 0.5 : 1,
        cursor: isDragging ? 'grabbing' : 'grab',
    }

    return (
        <div
            ref={setNodeRef}
            style={style}
            className={isDragging ? 'dragging-tab' : ''}
            {...attributes}
            {...listeners}
            onMouseEnter={() => !hasDragging && setIsHover(true)}
            onMouseLeave={() => !hasDragging && setIsHover(false)}
        >
            <ContextMenu
                items={[
                    {
                        label: (
                            <>
                                <IconEdit />
                                重命名
                            </>
                        ),
                        onClick: (e) => {
                            e.stopPropagation()
                            setEditingItem(item)
                        },
                    },
                    {
                        label: (
                            <>
                                <IconDelete className='!text-red-500' />
                                删除
                            </>
                        ),
                        onClick: (e) => {
                            e.stopPropagation()
                            handleDelete(item)
                        },
                    },
                ]}
            >
                {item.label}
            </ContextMenu>
            {(isHover || item.enabled) && (
                <Switch
                    checked={item.enabled}
                    onChange={(v, e) => {
                        e.stopPropagation()
                        handleGroupChange(item, v)
                    }}
                    size='small'
                    className='ml-2'
                />
            )}
        </div>
    )
}

export interface IGroupTabsRef {
    updateGroupData: () => void
}

export interface IGroupTabsProps {
    // 类名
    className?: string
    // 选中的组变化
    onSelectedGroupChange?: (groupId: string) => void
    // ref
    groupTabsRef?: React.RefObject<IGroupTabsRef | null>
}

const GroupTabs: React.FC<IGroupTabsProps> = ({
    groupTabsRef,
    onSelectedGroupChange,
    className,
}) => {
    // tab数据
    const [groupData, setGroupData] = useState<IGroupItem[][]>([])
    // 被选中的
    const [selectedIds, setSelectedIds] = useState<string[]>([''])
    // 正在编辑名称的项
    const [editingItem, setEditingItem] = useState<IListItem | undefined>()
    // 正在拖拽的 item id
    const [draggingId, setDraggingId] = useState<string | null>(null)

    // 配置拖拽传感器
    const sensors = useSensors(
        useSensor(PointerSensor, {
            activationConstraint: {
                distance: 8, // 移动8px后才开始拖拽，避免误触
            },
        }),
        useSensor(KeyboardSensor, {
            coordinateGetter: sortableKeyboardCoordinates,
        }),
    )

    // 初始化
    const initGroupData = async () => {
        setSelectedIds([''])
        queryGroupItems().then((items) => {
            setGroupData([items])
        })
        onSelectedGroupChange?.('')
    }

    // 更新组数据
    const updateGroupData = async (ids: string[] = selectedIds) => {
        const list = await apiStore.getAllList()
        const groupData: IGroupItem[][] = [
            list.filter(
                (v) => !v.parentId && v.type === 'group',
            ) as IGroupItem[],
        ]
        for (let i = 0; i < ids.length - 1; i++) {
            const id = ids[i]
            const items = list.filter(
                (v) => v.parentId === id && v.type === 'group',
            )
            groupData.push(items as IGroupItem[])
        }
        setGroupData(groupData)
    }

    // 更改enabled
    const handleGroupChange = async (item: IListItem, enabled: boolean) => {
        const cloned = { ...item }
        cloned.enabled = enabled
        await apiStore.save(cloned)
        Message.success('操作成功')
        updateGroupData()
    }

    // 删除分组
    const handleDelete = async (item: IListItem) => {
        Modal.confirm({
            title: '提示',
            content: '确定要删除该分组及分组下的所有API吗？删除后不可恢复',
            okButtonProps: {
                status: 'danger',
            },
            onOk: async () => {
                await apiStore.deleteGroup(item.id)
                // 更新当前选中的tab，如果当前选中的tab被删除了，则切换到上一级tab
                const index = selectedIds.indexOf(item.id)
                let newSelectedIds = selectedIds
                if (index !== -1) {
                    const newSelected = newSelectedIds[index - 1]
                    newSelectedIds = selectedIds.slice(0, index)
                    newSelectedIds.push(newSelected || '')
                    onSelectedGroupChange?.(newSelected || '')
                    setSelectedIds(newSelectedIds)
                }
                updateGroupData(newSelectedIds)
                Message.success('删除成功')
            },
        })
    }

    // 查询某个分组下的所有组
    const queryGroupItems = async (parentId?: string) => {
        const list = await apiStore.getList(parentId)
        const groupItems = list.filter((v) => v.type === 'group')
        return groupItems
    }

    // 重命名
    const handleRename = async (
        item?: IListItem,
        values?: { name: string },
    ) => {
        if (!item || !values) {
            return
        }
        const cloned = { ...item }
        cloned.label = values.name
        await apiStore.save(cloned)
        setEditingItem(undefined)
        Message.success('重命名成功')
        updateGroupData()
    }

    // 选中的tab变化
    const handleActiveTabChange = async (id: string, index: number) => {
        if (index === 0 && !id) {
            initGroupData()
            return
        }

        // 设置当前选中的id
        const newSelectedIds = selectedIds.slice(0, index + 1)
        newSelectedIds[index] = id
        // 组列表
        const newGroupData = groupData.slice(0, index + 1)
        // 如果不是选中的上一级tab，也就我在第
        if (newSelectedIds[index - 1] !== id) {
            newSelectedIds.push(id)
            const groupDataLine = await queryGroupItems(id)
            newGroupData.push(groupDataLine)
        }
        // 更新state
        setSelectedIds(newSelectedIds)
        setGroupData(newGroupData)
        // 更新列表
        onSelectedGroupChange?.(id)
    }

    // 处理拖拽开始
    const handleDragStart = (event: DragEndEvent) => {
        setDraggingId(event.active.id as string)
    }

    // 处理拖拽结束
    const handleDragEnd = async (event: DragEndEvent, levelIndex: number) => {
        const { active, over } = event

        // 清除拖拽状态
        setDraggingId(null)

        if (!over || active.id === over.id) {
            return
        }

        // 更新 store
        try {
            await apiStore.moveItem(active.id as string, over.id as string)
            // 重新从 store 加载数据
            await updateGroupData(selectedIds)
        } catch (error) {
            console.error('移动失败:', error)
        }
    }

    // 初始化
    useEffect(() => {
        initGroupData()
    }, [])

    if (groupTabsRef) {
        groupTabsRef.current = {
            updateGroupData,
        }
    }

    return (
        <>
            <div className={classNames('tabs-container', className)}>
                {groupData?.map((groupItems, index) => {
                    const selectedGroupId = selectedIds[index] || ''
                    const hasDragging = groupItems.some(
                        (item) => item.id === draggingId,
                    )

                    return (
                        <DndContext
                            key={selectedGroupId + index}
                            sensors={sensors}
                            collisionDetection={closestCenter}
                            onDragStart={handleDragStart}
                            onDragEnd={(event) => handleDragEnd(event, index)}
                        >
                            <SortableContext
                                items={groupItems.map((item) => item.id)}
                                strategy={horizontalListSortingStrategy}
                            >
                                <Tabs
                                    className='mb-1'
                                    type='rounded'
                                    activeTab={selectedIds[index]}
                                    onChange={(id) =>
                                        handleActiveTabChange(id, index)
                                    }
                                    renderTabTitle={(tabTitle) => {
                                        // 使用 React.cloneElement 创建新元素，避免修改只读 props
                                        const element =
                                            tabTitle as React.ReactElement<any>
                                        const currentClassName =
                                            element.props?.className || ''

                                        // 只要有拖拽发生，所有 tab 都添加透明背景
                                        return React.cloneElement(element, {
                                            ...element.props,
                                            className: hasDragging
                                                ? `${currentClassName} !bg-transparent`
                                                : currentClassName,
                                        })
                                    }}
                                >
                                    <TabPane
                                        key={selectedIds[index - 1] || ''}
                                        title={<span className='mx-2'>/</span>}
                                    />
                                    {groupItems?.map((item) => {
                                        return (
                                            <TabPane
                                                key={item.id}
                                                title={
                                                    <TabTitle
                                                        hasDragging={
                                                            hasDragging
                                                        }
                                                        item={item}
                                                        setEditingItem={
                                                            setEditingItem
                                                        }
                                                        handleDelete={
                                                            handleDelete
                                                        }
                                                        handleGroupChange={
                                                            handleGroupChange
                                                        }
                                                    />
                                                }
                                            />
                                        )
                                    })}
                                </Tabs>
                            </SortableContext>
                        </DndContext>
                    )
                })}
            </div>
            {/* 编辑分组弹窗 */}
            <AddGroupModal
                title='编辑分组'
                visible={!!editingItem}
                initialValues={{ name: editingItem?.label }}
                onCancel={() => setEditingItem(undefined)}
                onOk={(values) => handleRename(editingItem, values)}
                unmountOnExit
            />
        </>
    )
}

export default GroupTabs
